package com.chalk.config.security;

import com.chalk.common.constant.CommonConstants;
import com.chalk.common.exception.ServiceException;
import com.chalk.common.util.ResultCode;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * ClassName: UserDetailsUtil
 *
 * @author L.G
 * @Description User Details 工具类
 * @email lg10000@126.com
 * @date 2018年7月16日 下午4:25:55
 */
public class UserDetailsUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserDetailsUtil.class);

    /**
     * 获取当前用户信息
     *
     * @param classServiceName 获取用户信息service接口名称
     * @param paramName        查询参数名
     * @return 用户信息
     */
    public static Object getUserInfo(String classServiceName, String paramName) {
        Object object = null;
        try {
            UserDetails userDetails = null;
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            Object principal = authentication == null ? null : authentication.getPrincipal();
            if (principal instanceof UserDetails) {
                userDetails = (UserDetails) principal;
                String serviceName = classServiceName + "Impl";
                Object service = SpringContextUtil.getBean(serviceName);
                String methodName = "selectOne";
                Method method = service.getClass().getDeclaredMethod(methodName, Map.class);
                if (StringUtils.isNotBlank(userDetails.getUsername())) {
                    Map<String, Object> params = new HashMap<>();
                    params.put(paramName, userDetails.getUsername());
                    params.put("is_delete", CommonConstants.IsDeleted.NOTDEL.getValue());
                    /* 查询数据 */
                    object = method.invoke(service, params);
                }
            }
        } catch (Exception e) {
            LOGGER.error("获取用户信息异常:{}", ExceptionUtils.getStackTrace(e));
        }
        return object;
    }

    /**
     * 获取当前用户信息
     *
     * @param classs    获取用户信息service类
     * @param paramName 查询参数名
     * @return 用户信息
     */
    public static Object getUserInfo(Class<?> classs, String paramName) {
        Object object = null;
        try {
            UserDetails userDetails = null;
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            Object principal = authentication == null ? null : authentication.getPrincipal();
            if (principal instanceof UserDetails) {
                userDetails = (UserDetails) principal;
                String methodName = "selectByMap";
                Method method = classs.getDeclaredMethod(methodName, Map.class);
                Map<Object, Object> params = new HashMap<>();
                params.put(paramName, userDetails.getUsername());
                /* 查询数据 */
                object = method.invoke(classs, params);
            }
        } catch (Exception e) {
            LOGGER.error("获取用户信息异常:{}", ExceptionUtils.getStackTrace(e));
        }
        return object;
    }

    /**
     * 获取用户角色
     * @return
     */
    public static String[] getUserRoles(){
        UserDetails userDetail = getUserDetail();
        Collection<? extends GrantedAuthority> authorities = userDetail.getAuthorities();
        return authorities.toArray(new String[authorities.size()]);
    }


    private static UserDetails getUserDetail(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication == null){
            throw new ServiceException(ResultCode.NOT_LOGIN);
        }
        UserDetails userDetails = null;
        Object principal = authentication.getPrincipal();
        if (principal instanceof UserDetails) {
            return userDetails = (UserDetails) principal;
        }else{
            throw new ServiceException(ResultCode.USER_NOT_FOUND);
        }
    }
}
